#include "head.h"
//匿名管道的文件名描述符数组放在数据段，方便注册函数拿到
int pipe_fd[2];
//注册信号的函数
void exit_func(int num){
    write(pipe_fd[1],&num,sizeof(num));
}
int main(void)
{
    //创建匿名管道用于父子进程通信
    pipe(pipe_fd);
    //创建子进程，让子进程执行主体逻辑，父进程负责注册信号,等待子进程退出
    if(fork()!=0){
        signal(2,exit_func);
        wait(NULL);
        exit(0);
    }else{
        setpgid(0,0);
    }
    //创建公共资源结构体
    ShareValue sv;
    //初始化公共资源以及线程池
    initpool(&sv,4);

    // 读取配置文件，获得ip，port
    char ip[100];
    bzero(ip, sizeof(ip));
    getparameter("ip", ip);
    char port[10];
    bzero(port, sizeof(port));
    getparameter("port", port);

    //绑定端口ip，并创建socket
    int socket;
    create_socket(&socket,ip,port);

    //加入监听
    int epoll_fd=epoll_create(1);
    add_epoll(epoll_fd,socket);
    //父子进程通信的匿名管道读端加入监听
    add_epoll(epoll_fd,pipe_fd[0]);
    //记录客户端主线程连接信息
    connect_stat_t stat_list[10];
    bzero(stat_list,sizeof(stat_list));
    int len=0; 
    while(1){
        //超时踢出
        time_t timenow=time(NULL);
        for(int k=0;k<10;k++){
            if(stat_list[k].add_time!=0&&timenow-stat_list[k].add_time>=30){
                //关闭超时的socket，踢出客户主线程信息记录表
                printf("超时关闭fd:%d\n",stat_list[k].fd);
                close(stat_list[k].fd);
                stat_list[k].add_time=0;
                stat_list[k].fd=0;
                len--;
            }       
        }
        //开始监听
        struct epoll_event list[10];

        int num=epoll_wait(epoll_fd,list,10,1000);
        //子线程退出逻辑
        for(int i=0;i<num ;i++){
            if(list[i].data.fd==pipe_fd[0]){
                //由于水平触发模式，先接收数据
                char buf[60];
                bzero(buf,sizeof(buf));
                read(pipe_fd[0],buf,sizeof(buf));
                //通知子线程退出
                pthread_mutex_lock(&sv.lock_mutex);
                sv.exit_flag=1;
                pthread_mutex_unlock(&sv.lock_mutex);
                pthread_cond_broadcast(&sv.cond);
                //捕获退出的子线程
                for(int j=0;j<sv.num;j++){
                    pthread_join(sv.plist[j],NULL);
                }
                //所有子线程退出完成，主线程退出;
                exit(0);
            }
            //处理命令的主逻辑
            else if(list[i].data.fd==socket){
                //有新连接,创建客户socket对象，入队，唤醒线程
                int client_fd=accept(socket,NULL,NULL);
                //TODO:所有新连接加入监听
                add_epoll(epoll_fd,client_fd);
                LOG_WRITE(2,"有新的连接加入");
                //
                for(int i=0;i<10;i++){
                    if(stat_list[i].fd==0){
                        stat_list[i].fd=client_fd;
                        stat_list[i].add_time=time(NULL);
                        len++;
                        break;
                    }
                }


            }else{//进入这里就是用户端有输入命令
                  // TODO:recv(msg),接收消息
                int fd=list[i].data.fd;
                transport_protocol_t msg;
                bzero(&msg,sizeof(msg));
                int ret= recv(fd,&msg,sizeof(msg),0);
                //
                if(ret==0){
                    LOG_WRITE(2,"客户断开连接");
                    close(fd);
                    break;
                }
                for(int i=0;i<len;i++){
                    if(stat_list[i].fd==fd){
                        stat_list[i].add_time=time(NULL);
                    }
                }
                if(msg.command==1){//短命令

                    create_mysql(&msg.my_sql); 
                    if(strlen(msg.token)==0){//token为空说明未登录
                        login(fd,&msg);
                        break;
                    }  
                    int check=0;
                    send(fd,&check,4,0);
                    char *user_id;
                    analysis_is(&msg.my_sql,msg.token,&user_id);
                    memcpy(msg.user_id,user_id,sizeof(msg.user_id));

                    switch(msg.flag_work){
                    case 1:
                        ls(fd,&msg);
                        break;
                    case 2:
                        cd(fd,&msg);
                        break;
                    case 3:
                        rm(fd,&msg);
                        break;
                    case 4:
                        break;
                    case 7:
                        create_dir(fd,&msg);
                        break;
                    case 8:
                        ser_rmdir(fd,&msg);
                        break;
                    }
                }else{



                    // TODO:判断长短命令
                    //短命令主线程直接处理
                    //TODO:主线程处理短命令逻辑


                    //长命令入队
                    //

                    tail_insert(&sv.q,fd,msg);
                    //从监听中踢出子线程
                    if (epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, NULL) == -1) {
                        perror("epoll_ctl del"); // 如果失败，打印错误信息
                        exit(EXIT_FAILURE);      // 并退出程序
                    }
                    //从主线程客户信息表中踢出子线程客户
                    for(int i=0;i<10;i++){
                        if(stat_list[i].fd==fd){
                            stat_list[i].fd=0;
                            stat_list[i].add_time=0;
                            len--;
                            break;
                        }
                    }

                    pthread_cond_broadcast(&sv.cond);
                }
            }
        }
    }
}

